﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ResolverContracts.cs" company="Rolosoft Ltd">
//   © Rolosoft Ltd
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

#region License

// Copyright 2013 Rolosoft Ltd
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

namespace Rsft.Net.Dns.Interfaces
{
    #region Usings

    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Diagnostics.Contracts;
    using System.Net;

    using Rsft.Net.Dns.Entities;

    #endregion

    /// <summary>
    ///     The resolver contracts.
    /// </summary>
    [ContractClassFor(typeof(IResolver))]
    internal abstract class ResolverContracts : IResolver
    {
        #region Public Events

        /// <summary>
        ///     The verbose event.
        /// </summary>
        public virtual event EventHandler<VerboseEventArgs> VerboseEvent;

        /// <summary>
        /// Gets or sets the configuration.
        /// </summary>
        /// <value>
        /// The configuration.
        /// </value>
        public virtual IConfiguration Configuration { get; set; }

        #endregion
        
        #region Public Methods and Operators

        /// <summary>
        /// The begin get host addresses.
        /// </summary>
        /// <param name="hostNameOrAddress">
        /// The host name or address.
        /// </param>
        /// <param name="requestCallback">
        /// The request callback.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// The <see cref="IAsyncResult"/>.
        /// </returns>
        public virtual IAsyncResult BeginGetHostAddresses(
            string hostNameOrAddress, AsyncCallback requestCallback, object value)
        {
            Contract.Requires(!string.IsNullOrEmpty(hostNameOrAddress));
            Contract.Requires(requestCallback != null);

            Contract.Ensures(Contract.Result<IAsyncResult>() != null);

            return default(IAsyncResult);
        }

        /// <summary>
        /// The begin get host by address.
        /// </summary>
        /// <param name="address">
        /// The address.
        /// </param>
        /// <param name="asyncCallback">
        /// The async callback.
        /// </param>
        /// <param name="state">
        /// The state.
        /// </param>
        /// <returns>
        /// The <see cref="IAsyncResult"/>.
        /// </returns>
        public virtual IAsyncResult BeginGetHostByAddress(string address, AsyncCallback asyncCallback, object state)
        {
            Contract.Requires(!string.IsNullOrEmpty(address));
            Contract.Requires(asyncCallback != null);

            Contract.Ensures(Contract.Result<IAsyncResult>() != null);

            return default(IAsyncResult);
        }

        /// <summary>
        /// The begin get host by address.
        /// </summary>
        /// <param name="address">
        /// The address.
        /// </param>
        /// <param name="asyncCallback">
        /// The async callback.
        /// </param>
        /// <param name="state">
        /// The state.
        /// </param>
        /// <returns>
        /// The <see cref="IAsyncResult"/>.
        /// </returns>
        public virtual IAsyncResult BeginGetHostByAddress(IPAddress address, AsyncCallback asyncCallback, object state)
        {
            Contract.Requires(address != null);
            Contract.Requires(asyncCallback != null);

            Contract.Ensures(Contract.Result<IAsyncResult>() != null);

            return default(IAsyncResult);
        }

        /// <summary>
        /// The begin get host by name.
        /// </summary>
        /// <param name="hostName">
        /// The host name.
        /// </param>
        /// <param name="asyncCallback">
        /// The async callback.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// The <see cref="IAsyncResult"/>.
        /// </returns>
        public virtual IAsyncResult BeginGetHostByName(string hostName, AsyncCallback asyncCallback, object value)
        {
            Contract.Requires(!string.IsNullOrEmpty(hostName));
            Contract.Requires(asyncCallback != null);

            Contract.Ensures(Contract.Result<IAsyncResult>() != null);

            return default(IAsyncResult);
        }

        /// <summary>
        /// The begin get host entry.
        /// </summary>
        /// <param name="hostNameOrAddress">
        /// The host name or address.
        /// </param>
        /// <param name="asyncCallback">
        /// The async callback.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// The <see cref="IAsyncResult"/>.
        /// </returns>
        public virtual IAsyncResult BeginGetHostEntry(
            string hostNameOrAddress, AsyncCallback asyncCallback, object value)
        {
            Contract.Requires(!string.IsNullOrEmpty(hostNameOrAddress));
            Contract.Requires(asyncCallback != null);

            Contract.Ensures(Contract.Result<IAsyncResult>() != null);

            return default(IAsyncResult);
        }

        /// <summary>
        /// The begin get host entry.
        /// </summary>
        /// <param name="address">
        /// The address.
        /// </param>
        /// <param name="asyncCallback">
        /// The async callback.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// The <see cref="IAsyncResult"/>.
        /// </returns>
        public virtual IAsyncResult BeginGetHostEntry(IPAddress address, AsyncCallback asyncCallback, object value)
        {
            Contract.Requires(address != null);
            Contract.Requires(asyncCallback != null);

            Contract.Ensures(Contract.Result<IAsyncResult>() != null);

            return default(IAsyncResult);
        }
        
        /// <summary>
        /// Begins the query.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="queryType">Type of the query.</param>
        /// <param name="queryClassType">Type of the query class.</param>
        /// <param name="asyncCallback">The async callback.</param>
        /// <param name="state">The state.</param>
        /// <returns>
        /// The <see cref="IAsyncResult" />.
        /// </returns>
        public virtual IAsyncResult BeginQuery(
            string name, QType queryType, QClassType queryClassType, AsyncCallback asyncCallback, object state)
        {
            Contract.Requires(!string.IsNullOrEmpty(name));
            Contract.Requires(asyncCallback != null);

            Contract.Ensures(Contract.Result<IAsyncResult>() != null);

            return default(IAsyncResult);
        }

        /// <summary>
        /// The begin resolve.
        /// </summary>
        /// <param name="hostName">
        /// The host name.
        /// </param>
        /// <param name="asyncCallback">
        /// The async callback.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// The <see cref="IAsyncResult"/>.
        /// </returns>
        public virtual IAsyncResult BeginResolve(string hostName, AsyncCallback asyncCallback, object value)
        {
            Contract.Requires(!string.IsNullOrEmpty(hostName));
            Contract.Requires(asyncCallback != null);

            Contract.Ensures(Contract.Result<IAsyncResult>() != null);

            return default(IAsyncResult);
        }

        /// <summary>
        /// The end get host addresses.
        /// </summary>
        /// <param name="asyncResult">
        /// The async result.
        /// </param>
        /// <returns>
        /// The <see cref="IPAddress[]"/>.
        /// </returns>
        public virtual IPAddress[] EndGetHostAddresses(IAsyncResult asyncResult)
        {
            Contract.Requires(asyncResult != null);

            return default(IPAddress[]);
        }

        /// <summary>
        /// The end get host by address.
        /// </summary>
        /// <param name="asyncResult">
        /// The async result.
        /// </param>
        /// <returns>
        /// The <see cref="IPHostEntry"/>.
        /// </returns>
        public virtual IPHostEntry EndGetHostByAddress(IAsyncResult asyncResult)
        {
            Contract.Requires(asyncResult != null);

            return default(IPHostEntry);
        }

        /// <summary>
        /// The end get host by name.
        /// </summary>
        /// <param name="asyncResult">
        /// The async result.
        /// </param>
        /// <returns>
        /// The <see cref="IPHostEntry"/>.
        /// </returns>
        public virtual IPHostEntry EndGetHostByName(IAsyncResult asyncResult)
        {
            Contract.Requires(asyncResult != null);

            return default(IPHostEntry);
        }

        /// <summary>
        /// The end get host entry.
        /// </summary>
        /// <param name="asyncResult">
        /// The async result.
        /// </param>
        /// <returns>
        /// The <see cref="IPHostEntry"/>.
        /// </returns>
        public virtual IPHostEntry EndGetHostEntry(IAsyncResult asyncResult)
        {
            Contract.Requires(asyncResult != null);

            return default(IPHostEntry);
        }

        /// <summary>
        /// The end query.
        /// </summary>
        /// <param name="asyncResult">
        /// The async result.
        /// </param>
        /// <returns>
        /// The <see cref="Response"/>.
        /// </returns>
        public virtual Response EndQuery(IAsyncResult asyncResult)
        {
            Contract.Requires(asyncResult != null);

            return default(Response);
        }

        /// <summary>
        /// The end resolve.
        /// </summary>
        /// <param name="asyncResult">
        /// The async result.
        /// </param>
        /// <returns>
        /// The <see cref="IPHostEntry"/>.
        /// </returns>
        public virtual IPHostEntry EndResolve(IAsyncResult asyncResult)
        {
            Contract.Requires(asyncResult != null);

            return default(IPHostEntry);
        }

        /// <summary>
        /// The get arpa from enum.
        /// </summary>
        /// <param name="myEnum">
        /// The my enum.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public virtual string GetArpaFromEnum(string myEnum)
        {
            Contract.Requires(!string.IsNullOrEmpty(myEnum));

            return default(string);
        }

        /// <summary>
        /// The get arpa from ip.
        /// </summary>
        /// <param name="address">
        /// The address.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public virtual string GetArpaFromIp(IPAddress address)
        {
            Contract.Requires(address != null);

            return default(string);
        }

        /// <summary>
        /// The get host addresses.
        /// </summary>
        /// <param name="hostNameOrAddress">
        /// The host name or address.
        /// </param>
        /// <returns>
        /// The <see cref="IPAddress[]"/>.
        /// </returns>
        public virtual IPAddress[] GetHostAddresses(string hostNameOrAddress)
        {
            Contract.Requires(!string.IsNullOrEmpty(hostNameOrAddress));

            return default(IPAddress[]);
        }
        
        /// <summary>
        /// The get host by address.
        /// </summary>
        /// <param name="address">
        /// The address.
        /// </param>
        /// <returns>
        /// The <see cref="IPHostEntry"/>.
        /// </returns>
        public virtual IPHostEntry GetHostByAddress(IPAddress address)
        {
            Contract.Requires(address != null);

            return default(IPHostEntry);
        }

        /// <summary>
        /// The get host by address.
        /// </summary>
        /// <param name="address">
        /// The address.
        /// </param>
        /// <returns>
        /// The <see cref="IPHostEntry"/>.
        /// </returns>
        public virtual IPHostEntry GetHostByAddress(string address)
        {
            Contract.Requires(!string.IsNullOrEmpty(address));

            return default(IPHostEntry);
        }
        
        /// <summary>
        /// The get host by name.
        /// </summary>
        /// <param name="hostName">
        /// The host name.
        /// </param>
        /// <returns>
        /// The <see cref="IPHostEntry"/>.
        /// </returns>
        public virtual IPHostEntry GetHostByName(string hostName)
        {
            Contract.Requires(!string.IsNullOrEmpty(hostName));

            return default(IPHostEntry);
        }
        
        /// <summary>
        /// The get host entry.
        /// </summary>
        /// <param name="address">
        /// The address.
        /// </param>
        /// <returns>
        /// The <see cref="IPHostEntry"/>.
        /// </returns>
        public virtual IPHostEntry GetHostEntry(IPAddress address)
        {
            Contract.Requires(address != null);

            return default(IPHostEntry);
        }

        /// <summary>
        /// The get host entry.
        /// </summary>
        /// <param name="hostNameOrAddress">
        /// The host name or address.
        /// </param>
        /// <returns>
        /// The <see cref="IPHostEntry"/>.
        /// </returns>
        public virtual IPHostEntry GetHostEntry(string hostNameOrAddress)
        {
            Contract.Requires(!string.IsNullOrEmpty(hostNameOrAddress));

            return default(IPHostEntry);
        }

        /// <summary>
        /// Gets the host name of the local computer.
        /// </summary>
        /// <returns>
        /// A string that contains the DNS host name of the local computer.
        /// </returns>
        /// <PermissionSet>
        ///   <IPermission class="System.Net.DnsPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
        ///   </PermissionSet>
        public string GetHostName()
        {
            return default(string);
        }

        /// <summary>
        /// Queries the specified name.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="queryType">Type of the query.</param>
        /// <param name="queryClassType">Type of the query class.</param>
        /// <returns>
        /// The <see cref="Response" />.
        /// </returns>
        public virtual Response Query(string name, QType queryType, QClassType queryClassType = QClassType.IN)
        {
            Contract.Requires(!string.IsNullOrEmpty(name));

            return default(Response);
        }

        /*/// <summary>
        /// The query async.
        /// </summary>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <param name="qtype">
        /// The qtype.
        /// </param>
        /// <param name="cancellationToken">
        /// The cancellation token.
        /// </param>
        /// <param name="qClassType">
        /// The q class type.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        public virtual Task<Response> QueryAsync(
            string name, QType qtype, CancellationToken cancellationToken, QClassType qClassType = QClassType.IN)
        {
            Contract.Requires(!string.IsNullOrEmpty(name));

            Contract.Ensures(Contract.Result<Task<Response>>() != null);

            return default(Task<Response>);
        }*/

        /// <summary>
        /// The resolve.
        /// </summary>
        /// <param name="hostName">
        /// The host name.
        /// </param>
        /// <returns>
        /// The <see cref="IPHostEntry"/>.
        /// </returns>
        public virtual IPHostEntry Resolve(string hostName)
        {
            Contract.Requires(!string.IsNullOrEmpty(hostName));

            return default(IPHostEntry);
        }

        /// <summary>
        /// Begins the get TCP request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="asyncCallback">The async callback.</param>
        /// <param name="state">The state.</param>
        /// <returns>
        /// The <see cref="IAsyncResult" />
        /// </returns>
        public virtual IAsyncResult BeginGetTcpRequest(Request request, AsyncCallback asyncCallback, object state)
        {
            Contract.Requires(request != null);
            Contract.Requires(asyncCallback != null);
            Contract.Ensures(Contract.Result<IAsyncResult>() != null);

            return default(IAsyncResult);
        }

        /// <summary>
        /// Ends the get TCP request.
        /// </summary>
        /// <param name="asyncResult">The async result.</param>
        /// <returns>
        /// The <see cref="Response" />.
        /// </returns>
        public virtual Response EndGetTcpRequest(IAsyncResult asyncResult)
        {
            Contract.Requires(asyncResult != null);
            Contract.Ensures(Contract.Result<Response>() != null);

            return default(Response);
        }

        /// <summary>
        /// Begins the get UDP request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="asyncCallback">The async callback.</param>
        /// <param name="state">The state.</param>
        /// <returns>
        /// The <see cref="IAsyncResult" />
        /// </returns>
        public virtual IAsyncResult BeginGetUdpRequest(Request request, AsyncCallback asyncCallback, object state)
        {
            Contract.Requires(request != null);
            Contract.Requires(asyncCallback != null);
            Contract.Ensures(Contract.Result<IAsyncResult>() != null);

            return default(IAsyncResult);
        }

        /// <summary>
        /// Ends the get UDP request.
        /// </summary>
        /// <param name="asyncResult">The async result.</param>
        /// <returns>
        /// The <see cref="Response" />.
        /// </returns>
        public virtual Response EndGetUdpRequest(IAsyncResult asyncResult)
        {
            Contract.Requires(asyncResult != null);
            Contract.Ensures(Contract.Result<Response>() != null);
            return default(Response);
        }

        #endregion

        /*/// <summary>
        /// The resolve async.
        /// </summary>
        /// <param name="hostName">
        /// The host name.
        /// </param>
        /// <param name="cancellationToken">
        /// The cancellation token.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        public virtual Task<IPHostEntry> ResolveAsync(string hostName, CancellationToken cancellationToken)
        {
            Contract.Requires(!string.IsNullOrEmpty(hostName));

            Contract.Ensures(Contract.Result<Task<IPHostEntry>>() != null);

            return default(Task<IPHostEntry>);
        }*/
        #region Methods

        /// <summary>
        ///     The object invariant.
        /// </summary>
        [ContractInvariantMethod]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", 
            Justification = "Required for code contracts.")]
        private void ObjectInvariant()
        {
            Contract.Invariant(this.Configuration != null);
            Contract.Invariant(this.Configuration.Configuration.DnsServers != null);
            Contract.Invariant(this.Configuration.Configuration.DnsServers.Count > 0);
            Contract.Invariant(this.Configuration.Configuration.DnsTimeout >= 0);
            Contract.Invariant(this.Configuration.Configuration.Retries > 0);
            Contract.Invariant(this.Configuration.Configuration.TransportType == TransportType.Tcp || this.Configuration.Configuration.TransportType == TransportType.Udp);
        }

        #endregion
    }
}